



# 创建视图： 切片，reshape， view(), 转置（arr.T,  np.transpose(arr)）, arr.ravel()
# 创建副本： arr.copy()  花式索引（ arr[[0, 3]) ）, 数据类型转换（arr.astype(float)）, 展平（a.flatten()），分片（np.split(), np.hsplit())

# ravel 和 flatten ： 都是 多维变一维， ravel 数据内存可能不连续，   flatten内存连续

# ravel原理：直接引用原始数组的内存数据，不创建新数组。若原始数组内存连续（如 order='C'），则返回视图；若非连续（如转置数组），可能返回副本
# 当原数组非连续（如通过切片或转置生成）时，ravel() 可能返回副本
# reshape(-1) 与 ravel() 行为类似，默认返回视图

# order 参数（两者均支持）：
# 'C'：行优先（默认）
# 'F'：列优先
# 'A'：保留原顺序
# 'K'：按内存顺序展平


axis=0 # 垂直 方向，   1 水平方向

import numpy as np

arr = np.zeros((2,2))
print(arr)
ls = [i for i in range(12)]
print(ls)
arr = np.asarray(ls)
arr.reshape(3, 4)
print(arr)
arr = np.fromiter(ls)
genr = (i for i in range(12))
arr = np.fromiter(genr, dtype=np.int32)   # 接收生成器，只输出一维数据  当数据量超过百万后效果明显高于 np.array([]), 必须显式指定dtype​​
# np.loadtxt("xxx.txt")
np.genfromtxt("aaa.csv", delimiter=",")
arr.reshape(2,3, order="C") # 按行
arr.reshape(2,3, order="D") # 按列
np.resize(arr, (3,3)) # 平铺延展，123  ---> 123123123...
arr_view = arr.ravel()  # 将维度取消变为一维数组
arr = np.zeros((2, 4)) # 2行 4列
arr_view = arr.T # 4行 2列

# 1. 验证数据； 2.形状兼容性检测； 3.内存分配和复制数据（副本）
np.concatenate(arr, arr_view, axis=1)  # axis=None 数据展平
np.stack((arr, arr_view), axis=0)  # 默认0 垂直
np.vstack((arr, arr_view))  # v垂直 hstack水平

# concatenate vstack hstack 原理相同， 沿已有轴链接，不增加维度， --- 避免频繁拼接小数组
# stack 沿新轴堆叠，增加维度

a = arr.reshape(2,3).ravel()
b = arr.reshape(2,3).ravel()
np.add(a, b)
np.subtract(a, b)
np.multiply(a, b)
np.divide(a, b)
np.floor_divide(a, b)
np.power(a, 2)
np.mod(a, 3)
np.negative(a)  # 负号
np.positive(a)  # 正号
np.abs(a)
np.fabs(a) # 浮点数绝对值
np.rint(arr) # 四舍五入
np.sign(a)  # 提取符号，转换为： 0 -1 1
np.mean(a)   # 平均值  average 加权平均值
np.std(a) # 标准差
np.var(a)  # 方差
np.min(a)   # 等价 np.amin(arr) 最小值  同理 ：  max  amax 表示最大值
np.argmin(a) # 最小值位置
np.median(a) # 中位数
np.percentile(arr, 25)  # 百分位数
np.quantile(arr, 0.25) # 同上

np.all() # 所有元素为true   np.any() 任意元素为true

#  kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}
new_arr = np.sort(arr) # 返回排序数组，不修改原数组； 默认升序  降序需结合 [::-1]
arr.sort() #  对数组原地排序
# 会将 NaN 放在数组末尾


np.argmax(arr)  # 沿轴0(列方向)的最大值索引， 需要nan会报错  nanargmax忽略nan



np.unique(arr)  # 找到数组唯一值，等于去重，多维数组展平



# ---- 返回布尔数组 -----
np.equal(a, b)
np.not_equal(a, b)
np.less(a, b)
np.greater(a, b)
np.greater_equal(a, b)
# ---- 位操作 -----
np.bitwise_and(a, b)  # &   or-> |  xor 异或  not 取反===>  等价于 np.invert(a)
np.left_shift(a, 2)  # 左移 2 位


np.add.reduce(arr, axis=0)  # 垂直方向相加，得到维数 - 1   
np.multiply.reduce(arr, axis=0)  # 乘
arr.sum(axis=0)  #  等价   np.add.reduce(arr, axis=0)
arr.prod(axis=0) # ----> multiply

np.add.accumulate(a)  #  从左到右累计求和 np.multiply.accumulate(a)  累计和【 1， 1+2， 1+2+3】

indices= [0,3,4]
np.add.reduceat(arr, indices) # 分段求和  分别是  【0-3】 【3-4】 【4-最后】


# 指定索引处累加
arr = np.zeros(5, dtype=int)
indices = [0, 1, 1, 3]    #  在 1 索引位置 加了2次
np.add.at(arr, indices, 1)   # [1 2 0 1 0]




arr = np.array([3, 1, 4, 2, 5])
indices = np.argsort(arr)
print("原数组:", arr)        # [3 1 4 2 5]
print("排序索引:", indices)   # [1 3 0 2 4]
print("通过索引获取排序数组:", arr[indices])  # [1 2 3 4 5]



# 多字段排序，类似excl 中的多列
# np.lexsort((key1, key2, key3)) 的排序优先级是 key3 > key2 > key1（从右到左）。
# 类似于 SQL 的 ORDER BY key3, key2, key1
# np.argsort 只能按单个键排序，而 np.lexsort 支持多键排序。
# np.lexsort 适用于结构化数据或多列排序
# np.lexsort 会将 NaN 视为最大值，排在最后。
# 按姓氏排序，同姓氏按名字排序
surnames = np.array(['Zhang', 'Li', 'Wang', 'Li', 'Zhang'])
firstnames = np.array(['Hui', 'Lei', 'Fang', 'Xiang', 'Jing'])
# 注意：lexsort的键顺序是反的，最后面的键是主键
indices = np.lexsort((firstnames, surnames))
print("排序索引:", indices)  # [1 3 4 0 2]
# 显示排序结果
for i in indices:
    print(surnames[i], firstnames[i])

# 多列数据排序
data = np.array([
    [3, 1, 5],  # 假设三列分别是年龄、分数、ID
    [2, 3, 1],
    [3, 2, 3],
    [2, 3, 2]
])
# 先按年龄(第0列)排序，同年龄按分数(第1列)排序，最后按ID(第2列)排序
sorted_indices = np.lexsort((data[:, 2], data[:, 1], data[:, 0]))
print("多列排序结果:\n", data[sorted_indices])    




# 找出前3小的元素（不排序）
partitioned = np.partition(arr, 3)
# 获取前3小元素的索引
indices = np.argpartition(arr, 3)
# 找出最大的3个元素
indices = np.argpartition(arr, -3)[-3:]  # 最大的3个索引





sorted_arr = np.array([1, 3, 5, 7, 9])
# 查找单个元素的插入位置
pos = np.searchsorted(sorted_arr, 4)
print("4应插入的位置:", pos)  # 2 (在3和5之间)


# 插入多个元素
new_elements = np.array([2, 4, 6, 8])
positions = np.searchsorted(sorted_arr, new_elements)
print("插入位置:", positions)  # [1 2 3 4]

# 实际插入操作
result = np.insert(sorted_arr, positions, new_elements)
print("插入后数组:", result)  # [1 2 3 4 5 6 7 8 9]




# 形式1：查找满足条件的索引
arr = np.array([1, 2, 3, 4, 5])
indices = np.where(arr > 3)
# 形式2：条件选择
x = np.array([1, 2, 3, 4])
y = np.array([10, 20, 30, 40])
condition = np.array([True, False, True, False])
result = np.where(condition, x, y)
print("条件选择结果:", result)  # [1 20 3 40]
# 实际应用：将数组中大于3的值设为0，其余保持原样
arr = np.array([[1, 2, 3], 
                [4, 5, 6]])
modified = np.where(arr > 3, 0, arr)
"""
[[1 2 3]
 [0 0 0]]
"""


np.nonzero(arr)  # 非零元素索引 比 where(arr != 0) 更加高效
# 与where的区别
bool_arr = arr_2d > 1
print("where结果:", np.where(bool_arr))  # 与nonzero(bool_arr)相同
print("nonzero结果:", np.nonzero(bool_arr))  # 相同结果




print("整个数组的非零数:", np.count_nonzero(arr))  # 4
print("每行的非零数:", np.count_nonzero(arr, axis=1))  # [1 2 1]
print("每列的非零数:", np.count_nonzero(arr, axis=0))  # [1 1 2]




arr = np.array([1, 2, 3, 4, 5])
test_elements = np.array([2, 4, 6])
mask = np.isin(arr, test_elements)
print("成员测试结果:", mask)  # [False  True False  True False]
print("匹配的元素:", arr[mask])  # [2 4]


# 逆操作
print("不在集合中的元素:", arr[~mask])  # [1 3 5]



rng = np.random.default_rng()
rng.choice()


rng.uniform()



# np.clip 是 NumPy 库中的一个函数，用于对数组中的元素进行范围限制（也称为“裁剪”或“截断”）。
#   其核心功能是将数组中的值约束在指定的最小值和最大值之间，超出范围的值会被替换为边界值
# 比手动使用 np.where 或条件索引更高效，尤其处理大型数组时
#  使用场景： 数据标准化（归一化后约束在）， 图像处理（限制像素值在 [0, 255] 范围）， 异常值过滤（传感器数据中剔除噪声），考试成绩超过 100 分时设为 100
arr = np.array([-1, 5, 10, 15])
clipped = np.clip(arr, a_min=0, a_max=10)
print(clipped)  # 输出：[0, 5, 10, 10]

# ------- 二维 -------
data = np.array([1, 2, 3, 4])
min_bounds = np.array([1, 2, 3, 0])  # 每个元素的下限
max_bounds = np.array([1, 3, 4, 3])  # 每个元素的上限
result = np.clip(data, min_bounds, max_bounds)
print(result)  # 输出：[1, 2, 3, 3] [1,5]




